﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Mathematics;
using FreeGoo.GameEngine.Renderables.Links;

namespace FreeGoo.GameEngine.Renderables
{
    public class BodyHook : Renderable, ILinkable
    {
        private Vector2 _localPositon;
        private Vector2 _worldPosition;
        public BodyHook(BodyRenderable owningBodyRendrable, Vector2 worldPosition, float radius)
            : base()
        {
            OwningBodyRendrable = owningBodyRendrable;
            _worldPosition = worldPosition;
            _localPositon = OwningBodyRendrable.Body.GetLocalPosition(worldPosition);
            Radius = radius;
            Links = new List<Link>();
        }

        public float LastTestDistance { get; set; }
        public float Radius { get; set; }
        public IList<Link> Links { get; private set; }
        public BodyRenderable OwningBodyRendrable { get; private set; }
        public Vector2 BodyLinkAnchor { get { return _localPositon; } }

        public override Vector2 Position { get { return _worldPosition; } set { } }
        public override float Rotation { get { return OwningBodyRendrable.Rotation; } set { } }
        public Geom Geom { get { return OwningBodyRendrable.Geom; } }
        public Body Body { get { return OwningBodyRendrable.Body; } }
        public bool IsLinked { get { return Links.Count > 0; } }
        public IList<BodyHook> Siblings { get; set; }

        public override void UpdatePhysics()
        {
            base.UpdatePhysics();
            _worldPosition = OwningBodyRendrable.Body.GetWorldPosition(_localPositon);
        }

        public bool IsLinkedTo(ILinkable obj)
        {
            foreach (Link link in Links)
            {
                if (link.Linkable1 == obj || link.Linkable2 == obj)
                {
                    return true;
                }
            }

            if (Siblings != null && obj is BodyHook && Siblings.Contains(obj as BodyHook))
            {
                return true;
            }

            return false;
        }

        public bool ContainsLink(Link link)
        {
            return Links.Contains(link);
        }

        public virtual bool AllowsLinkFrom(ILinkable linkableBodyRenderable)
        {
            return true;
        }

        public virtual void AddLink(Link link)
        {
            Links.Add(link);
        }

        public virtual void RemoveLink(Link link)
        {
            Links.Remove(link);
        }

        public void ClearLinks()
        {
            while (Links.Count > 0)
            {
                Links[0].Delete();
            }
        }

        public override void AddToEngine(Engine engine)
        {
            base.AddToEngine(engine);
            engine.Linkables.Add(this);
        }

        public override void Delete()
        {
            base.Delete();
            Engine.Linkables.Remove(this);
        }
    }
}
